package com.chu.cloud.util;

import com.chu.cloud.enums.RedisKeyPrefix;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: Tianshu.CHU
 * @Date: 2018/3/24 11:38
 * @Description: redis工具类
 */
@Slf4j
public class RedisUtil {

    @SuppressWarnings("unchecked")
    private static RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) SpringContextHolder
            .getBean("redisTemplate");


    /**
     * 将value对象写入缓存
     *
     * @param prefix
     * @param key
     * @param value
     * @param expireTime
     */
    public static void set(RedisKeyPrefix prefix, Object key, Object value, int expireTime) {
        String finalKey = prefix.getPrefix() + key;
        redisTemplate.opsForValue().set(finalKey, value);
        expire(finalKey, expireTime);
    }

    /**
     * 将value对象写入缓存
     *
     * @param prefix
     * @param key
     * @param value
     */
    public static void set(RedisKeyPrefix prefix, Object key, Object value) {
        String finalKey = prefix.getPrefix() + key;
        redisTemplate.opsForValue().set(finalKey, value);
    }

    /**
     * 获取缓存<br>
     * 注：该方法暂不支持Character数据类型
     *
     * @param prefix Key前缀
     * @param key    key
     * @param clazz  类型
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T get(RedisKeyPrefix prefix, Object key, Class<T> clazz) {
        Assert.notNull(prefix, "redis prefix不能为空");
        Assert.notNull(key, "redis key不能为空");
        String finalKey = prefix.getPrefix() + key;
//        Jackson2JsonRedisSerializer<T> serializer = new Jackson2JsonRedisSerializer<T>(clazz);
//        serializer.setObjectMapper(JsonUtils.getInstance());
//        redisTemplate.setDefaultSerializer(serializer);
        return (T) redisTemplate.boundValueOps(finalKey).get();
    }

    public static void hSet(RedisKeyPrefix keyPrefix, Object key, Object field, Object value) {
        String finalKey = keyPrefix.getPrefix() + key;
        redisTemplate.opsForHash().put(finalKey, field, value);
    }

    public static <T> T hGet(RedisKeyPrefix keyPrefix, Object key, Object field) {
        String finalKey = keyPrefix.getPrefix() + key;
        return (T) redisTemplate.opsForHash().get(finalKey, field);
    }


    public static long delHash(RedisKeyPrefix keyPrefix, Object key,Object field){
        return redisTemplate.opsForHash().delete(keyPrefix.getPrefix(),key,field);
    }


    public static boolean hExist(RedisKeyPrefix keyPrefix, Object key, Object field) {
        String finalKey = keyPrefix.getPrefix() + key;
        return redisTemplate.opsForHash().hasKey(finalKey,field);
    }

    /**
     * 使key过期
     *
     * @param key
     * @param expireTime
     */
    public static void expire(String key, int expireTime) {
        redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
    }


    public static void del(RedisKeyPrefix keyPrefix, Object key) {
        String finalKey = keyPrefix.getPrefix() + key;
        redisTemplate.delete(finalKey);
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    public static boolean exists(RedisKeyPrefix keyPrefix, String key) {
        key = keyPrefix.getPrefix() + key;
        return redisTemplate.hasKey(key);
    }

    /**
     * 递减操作
     *
     * @param key
     * @param by
     * @return
     */
    public static long decr(String key, long by) {
        return redisTemplate.opsForValue().increment(key, -by);
    }

    /**
     * 递增操作
     * @param key
     * @param by
     * @param expireTime
     * @return
     */
    public static long incr(String key, long by,int expireTime) {
        Long increment = redisTemplate.opsForValue().increment(key, by);
        expire(key,expireTime);
        return increment;
    }

    /**
     * 递增操作
     *
     * @param key
     * @param by
     * @return
     */
    public static long incr(String key, long by) {
        return redisTemplate.opsForValue().increment(key, by);
    }


    public static <V> List<V> lrange(String key, int start, int end) {
        try {
            List<V> range = (List<V>) redisTemplate.opsForList().range(key, start, end);
            return range;
        } catch (Exception e) {
            log.error(e.getMessage());
            return new ArrayList<>();
        }
    }


}
